#    Copyright (C) 2018  Boris Bobrov
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <https://www.gnu.org/licenses/>.

import datetime
import logging
import os
import pathlib
import time

import daiquiri

from grab import Grab


daiquiri.setup(level=logging.INFO)

logger = daiquiri.getLogger(__name__)


QUERIES_DELAY = 3


class FormSubmissionFailure(Exception):
    pass


class NFOServer:
    
    def __init__(self, username, password, servername, typeofserver='virtual',
            cookies_file='~/.panel_cookies.json', grab_settings=None):
        self.username = username
        self.password = password
        self.servername = servername
        self.typeofserver = typeofserver
        p = pathlib.Path(cookies_file).expanduser()
        if not grab_settings:
            grab_settings = {}
        final_grab_settings = {
                'timeout': 10,
                'cookiefile': str(p),
                'user_agent': ('Mozilla/5.0 (Windows NT 6.2; WOW64)'
                              ' AppleWebKit/537.36 (KHTML like Gecko)'
                              ' Chrome/44.0.2403.155 Safari/537.36')
                }
        final_grab_settings.update(grab_settings)
        self.g = Grab(**final_grab_settings)

        # not sure how to correctly process cookies file, so lets do this:
        p.touch(mode=0o600, exist_ok=True)
        p.chmod(0o600)
        self._last_query_datetime = datetime.datetime.now()

    def _do_request(self, _method=None, *args, **kwargs):
        # making requests too often leads to an automated ban by ip. Lets not
        # make requests too often.
        time_passed = datetime.datetime.now() - self._last_query_datetime
        if time_passed.seconds < QUERIES_DELAY:
            wait_time = QUERIES_DELAY - time_passed.seconds
            logger.debug('Waiting for {} seconds'.format(wait_time))
            time.sleep(wait_time)
        resp = _method(*args, **kwargs)
        self._last_query_datetime = datetime.datetime.now()
        return resp

    def submit(self, *args, **kwargs):
        resp = self._do_request(self.g.submit, *args, **kwargs)
        if 'login.html' in resp.url:
            # form submission failed, raise an error about it
            raise FormSubmissionFailure('Form submission failed due to auth')

    def go(self, *args, **kwargs):
        resp = self._do_request(self.g.go, *args, **kwargs)
        if 'login.html' in resp.url:
            # auth required, lets try to auth and go again
            logger.info('Auth required, re-authenticating')
            self._authenticate()
            resp = self._do_request(self.g.go, *args, **kwargs)

    def _authenticate(self):
        self.g.doc.set_input('email', self.username)
        self.g.doc.set_input('password', self.password)
        self.submit()
        self.g.doc.text_assert('Welcome')
